package com.fast.fast.upms.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fast.fast.common.base.exception.BizException;
import com.fast.fast.upms.api.entity.SysDept;
import com.fast.fast.upms.api.vo.SysDeptVO;
import com.fast.fast.upms.biz.base.face.enums.TreeEnum;
import com.fast.fast.upms.biz.base.factory.TreeConvertFactory;
import com.fast.fast.upms.biz.base.util.TreeUtils;
import com.fast.fast.upms.biz.mapper.SysDeptMapper;
import com.fast.fast.upms.biz.service.SysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lyf
 * @description 针对表【sys_dept(系统部门表)】的数据库操作Service实现
 * @createDate 2022/01/01 00:00 周六
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept>
        implements SysDeptService {

    @Autowired
    private TreeConvertFactory treeConvertFactory;

    @Override
    public synchronized boolean saveOrUpdate(SysDept sysDept) {
        // 父节点不能是自己
        if (sysDept.getPid().equals(sysDept.getId())) {
            throw new BizException("父节点不能是自己");
        }
        // 如果当前节点的父节点改变时，需要重新设置排序值
        SysDept old = getById(sysDept.getId());
        if (!sysDept.getPid().equals(old.getPid())) {
            Integer sort = this.getMaxSortByPid(sysDept.getPid());
            sort++;
            sysDept.setSort(sort);
        }
        super.saveOrUpdate(sysDept);
        return true;
    }

    @Override
    public List<SysDeptVO> deptTree() {
        // 部门集合
        List<SysDept> sysDepts = list(Wrappers.lambdaQuery(SysDept.class)
                .orderByAsc(SysDept::getSort));
        // 获取包括所有子节点信息的父节点
        List<SysDept> nodes = sysDepts.stream().filter(sysDept -> sysDept.getPid() == 0)
                .map(o -> TreeUtils.listNodes(sysDepts, o))
                .collect(Collectors.toList());
        // 出参转换
        Object obj = treeConvertFactory.getConvert(TreeEnum.DEPT_TREE).convert(nodes);
        return (List<SysDeptVO>) obj;
    }

    @Override
    public List<SysDeptVO> deptTree2() {
        // 部门集合
        List<SysDept> sysDepts = list(Wrappers.lambdaQuery(SysDept.class)
                .orderByAsc(SysDept::getSort));
        // 获取包括所有子节点信息的父节点
        List<SysDept> nodes = sysDepts.stream().filter(sysDept -> sysDept.getPid() == 0)
                .map(o -> TreeUtils.listNodes(sysDepts, o))
                .collect(Collectors.toList());
        // 出参转换
        Object obj = treeConvertFactory.getConvert(TreeEnum.DEPT_TREE).convert2(nodes);
        return (List<SysDeptVO>) obj;
    }

    @Override
    public synchronized boolean addRoot(SysDept sysDept) {
        List<SysDept> sysDepts = list(Wrappers.lambdaQuery(SysDept.class)
                .eq(SysDept::getPid, 0L).select());
        // 根据父节点id获取父节点层级的最大排序值
        Integer sort = sysDepts.stream().map(SysDept::getSort).max(Integer::compare).orElse(0);
        sort++;
        sysDept.setSort(sort);
        save(sysDept);
        return true;
    }

    @Override
    public synchronized boolean addChild(JSONObject treeNode) {
        SysDept sysDept = new SysDept();
        String name = treeNode.getString("addNodeName");
        String code = treeNode.getString("addNodeCode");
        Long pid = treeNode.getLong("parentId");
        sysDept.setName(name);
        sysDept.setCode(code);
        sysDept.setPid(pid);
        // 根据父节点id获取父节点层级的最大排序值
        Integer sort = this.getMaxSortByPid(sysDept.getPid());
        sort++;
        sysDept.setSort(sort);
        save(sysDept);
        return true;
    }

    /**
     * 根据父节点id获取父节点层级的最大排序值
     *
     * @param pid
     * @return
     */
    private synchronized Integer getMaxSortByPid(long pid) {
        List<SysDept> sysDepts = list(Wrappers.lambdaQuery(SysDept.class)
                .eq(SysDept::getPid, pid));
        return sysDepts.stream().map(SysDept::getSort).max(Integer::compare).orElse(0);
    }
}




